% Copyright (C) 2023 Yassin Achengli <relifenatu@gmail.com> 
% Copyright (C) 2023 Jesús Bravo <js_bravo98@uma.es>
% 
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% any later version.
% 
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
% 
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

% -*- texinfo -*-
% @deftypefn {octave_qbits} {@var{out} =} qc_first_block ()
%
% This block generates the 4 combinated qbits state with each of the four 
% qbits as |0>. The combination returns a 4x1 column vector with a normalized
% state.
% 
% @ifnottex
% @example
%			|0> ---H-----o-----I----- | 
%			             |            |
%			|0> ---I-----X-----o----- |
%			                   |      |==> out
%			|0> ---I-----X-----X----- |
%			             |            |
%			|0> ---H-----o-----I----- |
% @end ifnottex
% @end example
%
% Params:
% @itemize
% @item @qcode{@var{out}} qbit state in question.
% @end itemsize
% @seealso{qc_second_block,qc_second_block_noCNOT}
% @end deftypefn
function out = qc_first_block()
    if ~exist('qc_defs_loaded'),
        load qc_defs.mat;
    end
    qb0 = [1;0];
    qc0 = kron(qb0, kron(qb0, kron(qb0,qb0)));
    CNOTi = [1 0 0 0; 
            0 0 0 1; 
            0 0 1 0; 
            0 1 0 0];
    op1 = kron(kron(H,I),kron(I,H));
    op2 = kron(CNOT, CNOTi);
    op3 = kron(I, kron(CNOT, I));

    out = op3 * op2 * op1 * qc0;
    out = out ./ max(out);
end

%!demo
%! "Salida sin normalizar:"
%! qc_first_block()
%! "Salida normalizada:"
%! qc_ket(qc_first_block())
%! "Qbits separados:"
%! qc_split(qc_first_block())
%! "Qbits separados sin normalizar:"
%! k = qc_split(qc_first_block());
%! k ./ max(k)
